package org.myorg.v5;

import java.util.Random;

public class FEvolution5 {
	/*
	 * 
	 * @param p_s 选择算子
	 * @param p_c 交叉算子 
	 * @param p_m 变异算子
	 */
	private double ps;
	private double pc;
	private double pm;


	public FEvolution5(double p_s, double p_c, double p_m) {
		ps = p_s;
		pc = p_c;
		pm = p_m;

	}

	/*
	 * 使用锦标赛的选择算法
	 */
	/*	public void select(FPeople5 p) {
		for (int i = 0; i < p.p_num; i++) {
			if (i == 0 || i == 1) {
				p.putPerson(p.getBest(),i);
			} else {
				int pos1 = (int) (Math.random()*p.p_num);
				int pos2 = (int) (Math.random()*p.p_num);
				if (p.personAt(pos1).fitness > p.personAt(pos2).fitness)
					p.putPerson(p.personAt(pos1), i);
				else
					p.putPerson(p.personAt(pos2), i);
			}

		}
	}*/

	/*
	 * fast non-dominated sorting based on tree
	 * Q: children people
	 * P: parent people
	 */
	public void select(FPeople5 Q, FPeople5 P) {
		Q.add(P);
		Tree_fs tf = new Tree_fs();
		Q.clone(tf.td(Q));
		
	}

	/*
	 * 单点交叉
	 */

	/*public void crossOver(FPeople5 p) {
		for (int i=0; i < p.p_num-1; i++) {
			if (Math.random() > pc) {
				int cross_pos = (int) (Math.random()*p.getPersons()[0].length);

				String temp1 = p.getPersons()[i].gene.substring(0,cross_pos)
				+p.getPersons()[i+1].gene.substring(cross_pos);

				p.getPersons()[i+1].gene = p.getPersons()[i+1].gene.substring(0,cross_pos)
				+p.getPersons()[i].gene.substring(cross_pos);

				p.getPersons()[i].gene = temp1;
			}
		}
	}*/
	/*
	 * 双点交叉
	 */
	
	public void crossOver(FPeople5 p) {
		FPeople5 old = new FPeople5(p);
		int pop_size = p.p_num;
		int[] a1 = new int[pop_size];
		int[] a2 = new int[pop_size];
		for (int i = 0; i < pop_size; i++) {
			a1[i] = i;
			a2[i] = i;
		}
		
		
		for (int i = 0; i < pop_size; i++) {
			int r = (int) Math.floor(Math.random() * pop_size);
			int tmp = a1[i];
			a1[i] = a1[r];
			a1[r] = tmp;
			
			r = (int) Math.floor(Math.random() * pop_size);
			tmp = a2[i];
			a2[i] = a2[r];
			a2[r] = tmp;
		}
		
		for (int i=0; i < pop_size; i = i+4) {
			
			if (Math.random() < pc) {
				//gene length
				int  gl = p.getPersons()[0].length;
				// crossover position
				int cp1 = (int) Math.floor((Math.random()*(gl + 1)));
				int cp2 = (int) Math.floor((Math.random()*(gl + 1)));
				
				while(cp1%p.getPersons()[0].sl != 0) {
					cp1++;
				}
				
				while(cp2%p.getPersons()[0].sl != 0) {
					cp2++;
				}
				
				if (cp1 > cp2) {
					int tmp = cp1;
					cp1 = cp2;
					cp2 = tmp;
				}

				
				FGene5 p1 = old.persons[a1[i]];
				FGene5 p2 = old.persons[a1[i + 2]];
				if (a1[i] > a1[i+1])
					p1 = old.persons[a1[i+1]];
				if (a1[i + 2] > a1[i+3])
					p2 = old.persons[a1[i+3]];
				
				String s1 = p1.gene.substring(0,cp1) + 
				p2.gene.substring(cp1, cp2) +
				p1.gene.substring(cp2);
				
				String s2 = p2.gene.substring(0,cp1) + 
				p1.gene.substring(cp1, cp2) +
				p2.gene.substring(cp2);
				
				p.persons[i].gene = s1;
				p.persons[i + 1].gene = s2;
				
				// crossover position
				cp1 = (int) (Math.random()*(gl + 1));
				cp2 = (int) (Math.random()*(gl + 1));
				
				if (cp1 > cp2) {
					int tmp = cp1;
					cp1 = cp2;
					cp2 = tmp;
				}

				//System.out.println("cp1 = " + cp1 + "cp2 = " + cp2);
				
				p1 = old.persons[a2[i]];
				p2 = old.persons[a2[i + 2]];
				if (a2[i] > a2[i+1])
					p1 = old.persons[a2[i+1]];
				if (a2[i+2] > a2[i+3])
					p2 = old.persons[a2[i+3]];
				
				s1 = p1.gene.substring(0,cp1) + 
				p2.gene.substring(cp1, cp2) +
				p1.gene.substring(cp2);
				
				s2 = p2.gene.substring(0,cp1) + 
				p1.gene.substring(cp1, cp2) +
				p2.gene.substring(cp2);
				
				p.persons[i + 2].gene = s1;
				p.persons[i + 3].gene = s2;
			}
		}
	}

	/*
	 * 单点变异
	 */
	public void mutation(FPeople5 p) {

		// gene length
		int gl = p.persons[0].getLength();
		for(int i = 0; i < p.p_num; i++) {
			//		int i = 0;
			//		if(Math.random() > 0.5)
			//			i = 1;
			if (p.getPersons()[0].gene_type == 1){ //binary mutation
				for(int j = 0; j < gl; j++) {
					if (Math.random() < pm) {
						char temp[]; 

						/*System.out.println(i + "  j = " + j);
						System.out.println("gene length " + p.getPersons()[i].gene.length());
						System.out.println("gene " + p.getPersons()[i].gene);*/
						if (p.getPersons()[i].gene.charAt(j) == '0') {
							temp = p.getPersons()[i].gene.toCharArray();
							temp[j] = '1';
							p.getPersons()[i].gene = new String(temp);
						} else {
							temp = p.getPersons()[i].gene.toCharArray();
							temp[j] = '0';
							p.getPersons()[i].gene= new String(temp);
						}
					}
				}
			}
			else if (p.getPersons()[0].gene_type == 0){

			}
			else {
				for(int j = 0; j < gl; j++) { //integer mutation
					if (Math.random() < pm) {
						char temp[],temp1; 

						int i_tem = (int) Math.floor(Math.random()*p.getPersons()[i].gene_type);
						String tmp = Integer.toString(i_tem);
						while(tmp.length()<p.getPersons()[i].sl) {
							tmp = "0" + tmp;
						}
						//temp = p.getPersons()[i].gene.toCharArray();
						//temp1 = Integer.toString(i_tem).charAt(0);
						//temp[j] = temp1;
						p.getPersons()[i].gene = p.getPersons()[i].gene.substring(0, j*p.getPersons()[i].sl) + 
						tmp + p.getPersons()[i].gene.substring((j+1)*p.getPersons()[i].sl); 

					}
				}
			}
		}
	}
}

